#include <stdio.h>
#include <stdlib.h>
#include "hi_voice_api.h"

#define VOICE_FRAME_SIZE           160  /* VOICE_FRAME_SIZE <= HI_VOICE_MAX_FRAME_SIZE */



HI_S32 VoiceEngineState[0x100], VoiceEngineTransState[0x200];

static void proc_head ()
{
    fprintf(stderr,"\n\
**************************************************************\n\
\n\
               Hisilicon VoiceEngine \n\
\n\
     Speech codec for G.711/ADPCM/G.726/G.728/G.729AB\n\
\n\
     Bit-Exact C Simulation Code \n\
\n\
     Version 1.1.0   March 26, 2007\n\
**************************************************************\n",
  "");
}
static void proc_invalid_para(char *mes)
{
        printf("\n%s parameters is invalid!\n", mes);
        printf("\nHisiVoiceEngine.exe codectype codec infile outfile vad\n");
        printf("***** codectype (for RTP/ASF Format) *****\n");
        printf("    Real-time transport protocol(RTP) Format \n");
		printf("      0x01: 64kbps G.711 A \n");
        printf("      0x02: 64kbps G.711 U \n");
        printf("      0x03: 32kbps DVI4 ADPCM \n");
        printf("      0x04: 16kbps G.726 \n");
        printf("      0x05: 24kbps G.726 \n");
        printf("      0x06: 32kbps G.726 \n");
        printf("      0x07: 40kbps G.726 \n");
        printf("    Advanced Systems Format (ASF) \n");
		printf("      0x01: 64kbps G.711 A \n");
        printf("      0x02: 64kbps G.711 U \n");
        printf("      0x23: 32kbps IMA ADPCM \n");
        printf("      0x24: 16kbps G.726 \n");
        printf("      0x25: 24kbps G.726 \n");
        printf("      0x26: 32kbps G.726 \n");
        printf("      0x27: 40kbps G.726 \n");
        printf("      0x61: origine G.711A transform to RTP G.711A \n");
		printf("      0x62: origine G.711U transform to RTP G.711U \n");
		printf("      0x63: origine DVI4_ADPCM transform to RTP DVI4_ADPCM \n");
		printf("      0x64: origine 16kbps G.726 transform to RTP 16kbps G.726\n");
        printf("***** codec **************************\n");
        printf("      0: encoder \n");
        printf("      1: decoder \n");
   	    printf("      2: transform code \n");
        printf("***** vad (only for encoder)**********\n");
        printf("      0: disable \n");
        printf("      1: enable \n");
        printf("VoiceEngine, 1,      0,       infile, outfile, 1      \n");
        printf("VoiceEngine, G711_A, Encoder, infile, outfile, VAD_EN \n");
}

char g_CoderName[7][64] = {
 "G.711 a 64kbps ",
 "G.711 u 64kbps ",
 "ADPCM(DVI4) 32kbps ",
 "G.726 16kbps ",
 "G.726 24kbps ",
 "G.726 32kbps ",
 "G.726 40kbps ",
};


int main(int argc, char *argv[])
{
#if 1
	FILE *fp_in=NULL,*fp_out=NULL;
	HI_S16 ou_dec_pcmbuf[HI_VOICE_MAX_FRAME_SIZE];     //decoder output
	HI_S16 in_enc_pcmbuf[HI_VOICE_MAX_FRAME_SIZE];     //encoder input
	HI_S16 ou_enc_unpacked[HI_VOICE_MAX_FRAME_SIZE];   //encoder output
	HI_S32 frame;
	HI_S16 coder, codectype, len, vad, frame_size;
	VOICE_VERSION_S pVersion;

#if 1	
    /* VoiceEngine.exe codectype codec infile outfile vad */
	argc = 0;
    argv[argc++] = "VoiceEngine";
    argv[argc++] = "1";
    argv[argc++] = "1";
    argv[argc++] = "E:\\vector\\G.7xx\\OLD\\new_G711A.dat";
    argv[argc++] = "E:\\vector\\G.7xx\\OLD\\new_G711A.pcm";
#endif

/*
	if(!HI_VOICE_GetVersion(&pVersion))
	    printf("%s\n",pVersion.aVersion);
*/
	
	proc_head();
	if((argc != 6) && (argc != 5))
    {
 	    proc_invalid_para("");
        getchar();
        exit(1);
    }
	
	coder     = atoi(argv[1]);
	codectype = atoi(argv[2]);
    fp_in     = fopen(argv[3], "rb");
    fp_out    = fopen(argv[4], "wb");            

	if( (coder!=G711_A) && (coder!=G711_U) &&(coder!=ADPCM_DVI4)&&\
		(coder!=G726_16KBPS) && (coder!=G726_24KBPS) &&(coder!=G726_32KBPS)&&\
		(coder!=G726_40KBPS) && \
		(coder!=ADPCM_IMA)&&\
		(coder!=MEDIA_G726_16KBPS) && (coder!=MEDIA_G726_24KBPS) &&(coder!=MEDIA_G726_32KBPS)&&\
		(coder!=MEDIA_G726_40KBPS) && (coder!=G726_ORG_16KBPS) && \
		(coder!=G711_ORG_A) && \
		(coder!=G711_ORG_U) && \
		(coder!=ADPCM_ORG_DVI4) && \
        (coder!=ORG_G711A_TRANSF2_G711A) && \
		(coder!=ORG_G711U_TRANSF2_G711U) && \
		(coder!=ORG_ADPCM_DVI4_TRANSF2_ADPCM_DVI4)  && \
        (coder!=ORG_G726_16KBPS_TRANSF2_G726_16KBPS)
	){
	   proc_invalid_para("codectype");
       getchar();
       exit(1);
	}

    if((codectype != 0) && (codectype != 1) && (codectype != 2))
	{
	   proc_invalid_para("codec");
       getchar();
       exit(1);
	}

	if(argc==6)
	{
		vad = atoi(argv[5]);          /* reserved */
		if((vad != 0) && (vad != 1))
		{
		   proc_invalid_para("vad");
           getchar();
           exit(1);
		}
	}
    if ( (fp_in == NULL)) 
    {
       printf(" Error opening infile %s !!\n",argv[3]); 
	   getchar(); exit(0);
    }
    if ( (fp_out == NULL)) 
    {
       printf(" Error opening outfile %s !!\n",argv[4]); 
	   getchar(); exit(0);
    }
    
	frame_size = VOICE_FRAME_SIZE;
	if( frame_size > (HI_VOICE_MAX_FRAME_SIZE-1))
    {
       printf(" Error input frame size !!\n"); 
	   getchar(); exit(0);
    }

	if(coder==ADPCM_IMA)
       frame_size += 1;

	frame = 0;
    if(codectype == 0){ 	/* encoder */
		HI_VOICE_EncReset((HI_VOID*)VoiceEngineState, coder);
		while( fread(in_enc_pcmbuf, sizeof(HI_S16), frame_size, fp_in)==(HI_U32)frame_size)
		{
			HI_VOICE_EncodeFrame((HI_VOID*)VoiceEngineState, in_enc_pcmbuf, ou_enc_unpacked, frame_size);
            fwrite(ou_enc_unpacked, sizeof(HI_S16), 2+ou_enc_unpacked[1], fp_out);
			frame++;
			printf("%s encoding %d frame\r", g_CoderName[(coder&0x1f)-1], frame);
		}
	}
	else if(codectype == 1)
	{

        HI_VOICE_DecReset((HI_VOID*)VoiceEngineState, coder);
        while (fread(&ou_enc_unpacked[0], sizeof(HI_S16), 2, fp_in) == 2)
        {
			len = (ou_enc_unpacked[1]&0x00ff);
			if(fread(&ou_enc_unpacked[2], sizeof(HI_S16), len, fp_in) != (HI_U32)(len) )
				break;

            HI_VOICE_DecodeFrame((HI_VOID*)VoiceEngineState, ou_enc_unpacked, ou_dec_pcmbuf, &len);
			fwrite(ou_dec_pcmbuf, sizeof(HI_S16), len, fp_out);
			frame++;
			printf("%s decoding %d frame\r", g_CoderName[(coder&0x1f)-1], frame);
        }
    }      
    else
    {
        HI_VOICE_TransCodeReset((HI_VOID*)VoiceEngineTransState, coder);
            
        while (fread(&ou_enc_unpacked[0], sizeof(HI_S16), 2, fp_in) == 2)
        { 
            len = (ou_enc_unpacked[1]&0x00ff);
	    	if(fread(&ou_enc_unpacked[2], sizeof(HI_S16), len, fp_in) != (HI_U32)(len) )
		    break;	
            
            HI_VOICE_TransCodeFrame((HI_VOID*)VoiceEngineTransState, ou_enc_unpacked);
            len = (ou_enc_unpacked[1]&0x00ff) + 2;
            fwrite(ou_enc_unpacked, sizeof(HI_S16), len, fp_out);
		    frame++;
	    	printf("transform origion %s to %s %dframe\r", g_CoderName[(coder&0x0f)-1], 
                                                           g_CoderName[(coder&0x0f)-1], frame);
	    }
     }
        
    printf("\n\n");
    fclose(fp_in);
    fclose(fp_out);

	return 0;
#endif

 }
